import json
import random
import re

from django.http import HttpResponse
from django.http import JsonResponse

# Create your views here.
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from libs.captcha.captcha import captcha
from libs.yuntongxun.sms import CCP
from oauth.utils import *
from user.models import User

from . import constants
from utils.response_code import *


# 获取验证码图片和文本
class ImageCodeView(View):
    def get(self, request, image_code_id):
        # 1.接收数据

        # 2.校验数据
        # 3.处理业务
        # 获取图片文本和图片二进制代码
        text, image = captcha.captcha.generate_captcha()
        # 把uuid存入redis
        # 获取redis客户端
        redis_client = get_redis_connection('verify_code')
        # 写入redis
        # 获取从js文件得到的uuid,将uuid作为键,图片文本作为值写入redis,中间的参数为該值存在的毫秒时间
        redis_client.setex(image_code_id, constants.REDIS_IMAGE_CODE_EXPIRE, text)

        # 4.返回响应
        return HttpResponse(image, content_type='image/jpg')

# 发送短信验证码
class SMSCodeView(View):
    def get(self, request, mobile):
        # 获取数据
        # 数据为js文件以get方式通过url传参传入
        data = request.GET
        image_code = data.get('image_code')
        image_code_id = data.get('image_code_id')
        # 校验数据
        if not all([image_code, image_code_id]):
            return JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': err_msg.get(RETCODE.NECESSARYPARAMERR)})
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': RETCODE.MOBILEERR, 'errmsg': err_msg.get(RETCODE.MOBILEERR)})
        # 连接缓存图片文本的redis数据库
        redis_cline = get_redis_connection('verify_code')
        # 通过uuid获取图片文本
        redis_code = redis_cline.get(image_code_id)
        # 因为redis是以二进制格式存储数据,所以如果此时redis缓存还存在需要对其解码
        if redis_code:
            redis_code = redis_code.decode()
            # 解码完成后已经用变量接收了数据内容,此时可以删除缓存数据避免资源占用
            redis_cline.delete(image_code_id)
        else:
            # 主要应对超时问题
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码失效'})
        if redis_code != image_code.upper():
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': err_msg.get(RETCODE.IMAGECODEERR)})

        # 处理业务
        redis_flag = redis_cline.get('flag_%s' % mobile)
        if redis_flag:
            return JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': err_msg.get(RETCODE.THROTTLINGERR)})
        # 以上图片验证码的检验都通过后,执行发送短信功能
        # 生成四位数的短信验证码
        sms_code = "%04s" % random.randint(0, 9999)
        print('短信验证码:'+sms_code)
        # 将验证码存储到以电话为键的redis缓存数据库中
        redis_cline.setex(mobile, constants.REDIS_SMS_CODE_EXPIRE, sms_code)
        redis_cline.setex('flag_%s' % mobile, constants.REDIS_SENDING_SMS_CODE_EXPIRE, 1)
        # 返回响应
        # 发送短信
        # ccp = CCP()
        # ccp.send_template_sms(mobile, [sms_code, constants.REDIS_SMS_CODE_EXPIRE//60], 1)
        # 调用celery异步调用实现短信发送
        # from main import send_sms_code
        # send_sms_code.delay(mobile, sms_code, constants.REDIS_SMS_CODE_EXPIRE // 60)

        res = {
            'code': 0,
            'errmsg': '短信发送成功'
        }

        return JsonResponse(res)

# 找回密码
class AccountsView(View):
    def get(self,request,username):
        # 1.接收数据
        data = request.GET.dict()
        image_code = data['text']
        image_code_id = data['image_code_id']
        # 2.检验数据
        # if not all([image_code_id,image_code]):
        #     return JsonResponse({'code':9999,'errmsg':'验证码出错'},status=400)
        try:
            user = User.objects.get(mobile=username)
        except Exception as e:
            try:
                user = User.objects.get(username=username)
            except Exception as e:
                return JsonResponse({'code': 9999, 'errmsg': '用户名或手机号错误'})
        # 3.处理业务
        redis_conn = get_redis_connection('verify_code')
        redis_code = redis_conn.get(image_code_id)
        if redis_code:
            redis_code = redis_code.decode()
            # 解码完成后已经用变量接收了数据内容,此时可以删除缓存数据避免资源占用
            redis_conn.delete(image_code_id)
        else:
            # 主要应对超时问题
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码失效'},status=400)
        if redis_code != image_code.upper():
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': err_msg.get(RETCODE.IMAGECODEERR)},status=400)
        mobile = user.mobile
        access_token = encode_openid(mobile)
        mobile = mobile[:3]+"****"+mobile[7:]
        res ={
            'code':0,
            'mobile':mobile,
            'access_token': access_token
        }
        response = JsonResponse(res)
        # response.set_cookie('username')
        # 4.返回响应
        return response

class FindPasswordSMSView(View):
    def get(self,request):

        # 1.接收数据
        access_token = request.GET.get('access_token')
        mobile = decode_openid(access_token)
        # 2.检验数据
        redis_cline = get_redis_connection('verify_code')
        redis_flag = redis_cline.get('flag_%s' % mobile)
        if redis_flag:
            return JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': err_msg.get(RETCODE.THROTTLINGERR)})
        # 3.处理业务
        sms_code = "%04s" % random.randint(0, 9999)
        print('短信验证码:' + sms_code)
        # 将验证码存储到以电话为键的redis缓存数据库中
        redis_cline.setex(mobile, constants.REDIS_SMS_CODE_EXPIRE, sms_code)
        redis_cline.setex('flag_%s' % mobile, constants.REDIS_SENDING_SMS_CODE_EXPIRE, 1)
        # 返回响应
        # 发送短信
        # ccp = CCP()
        # ccp.send_template_sms(mobile, [sms_code, constants.REDIS_SMS_CODE_EXPIRE//60], 1)
        # 调用celery异步调用实现短信发送
        # from main import send_sms_code
        # send_sms_code.delay(mobile, sms_code, constants.REDIS_SMS_CODE_EXPIRE // 60)
        # 4.返回响应
        res={
            'code':0,
            'errmsg':'成功'
        }
        return JsonResponse(res)

class FindPasswordSubmitSMSView(View):
    def get(self,request,username):
        # 1.接收数据
        sms_code = request.GET.get('sms_code')

        # 2.检验数据
        try:
            user = User.objects.get(username=username)
        except Exception as e:
            try:
                user = User.objects.get(mobile=username)
            except Exception as e:
                return JsonResponse({'code': 9999, 'errmsg': '用户名或手机号错误'})
        # 3.处理业务
        redis_conn = get_redis_connection('verify_code')
        mobile = user.mobile
        redis_sms = redis_conn.get(mobile)
        if redis_sms:
            redis_sms = redis_sms.decode()
            redis_conn.delete(mobile)
            redis_conn.delete('flag_%s'%mobile)
        else:
            # 主要应对超时问题
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '验证码失效'}, status=400)
        if redis_sms != sms_code:
            return JsonResponse({'code':9999,'errmsg':'验证码错误'},status=400)
        # 4.返回响应
        res = {
            'code':0,
            'errmsg':'成功',
            'access_token':encode_openid(mobile),
            'user_id':user.id
        }
        return JsonResponse(res)
class ChangePasswordView(View):
    def post(self,request,user_id):
        """
        password: this.password,
        password2: this.password2,
        access_token: this.access_token
        """

        # 1.接收数据
        data = json.loads(request.body.decode())
        password1 = data['password']
        password2 = data['password2']
        access_token = data['access_token']
        # 2.检验数据
        mobile = decode_openid(access_token)
        if password1 != password2:
            return JsonResponse({'code':9999,'errmsg':'两次输入的密码不一致'})
        # 3.处理业务
        try:
            user = User.objects.get(id=user_id,mobile=mobile)
        except Exception as e:
            return JsonResponse({'code':9999,'errmsg':'用户信息有误'})
        user.set_password(password1)
        user.save()
        # 4.返回响应
        res={
            'code':'0',
            'errmsg':'成功',
        }
        return JsonResponse(res)

